/*  This file is part of CASpp.

    CASpp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CASpp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CASpp.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2014 Jérome LAURENS

    See https://code.google.com/p/idalgo/

*/

#if !defined _CASPP_MODELS_H_
#define _CASPP_MODELS_H_

#include <string>
#include "config.h"

#include "terminals/boolean.h"
#include "terminals/integer.h"
#include "terminals/rational.h"
#include "terminals/real.h"
#include "terminals/string.h"
#include "terminals/symbol.h"
#include "terminals/variable.h"
#include "non_terminals/list.h"
#include "non_terminals/map.h"
#include "non_terminals/set.h"
#include "non_terminals/vector.h"
#include "non_terminals/function.h"

#include <boost/variant.hpp>

CASPP_NS_BEGIN

typedef boost::variant<
      BooleanRef
    , StringRef
    , ListRef
    , VectorRef
    , SetRef
    , MapRef
    , IntegerRef
    , RationalRef
    , RealRef
    , SymbolRef
    , VariableRef
    , FunctionRef
> Agregate;

class GetNumberDot {
public:
    char operator()() const;
};

template <typename T>
class Description {
public:
    typedef T type_t;
    const std::string operator() (const Boolean & __x);
    const std::string operator() (const String & n);
    const std::string operator() (const List & n);
    const std::string operator() (const Vector & n);
    const std::string operator() (const Set & n);
    const std::string operator() (const Map & n);
    const std::string operator() (const Integer & __x, const int base);
    const std::string operator() (const Integer & __x);
    const std::string operator() (const Rational & __x, const int base);
    const std::string operator() (const Rational & __x);
    const std::string operator() (const Real & __x);
    const std::string operator() (const Real & __x
                            , bool wrap
            , const type_t & getNumberDot
            , const size_t n = 0
            , const Rounding::Values rnd = Rounding::Nearest
            , const int base = 10);
    const std::string operator() (const Symbol & n);
    const std::string operator() (const Variable & n);
    const std::string operator() (const Function & n);
};

template <typename T>
class t_AgregateDescriptionVisitor: public boost::static_visitor<const std::string>
{
public:
    template <typename TRef>
    result_type operator() (const TRef & t) const {
        return t.get()? T()(*t):"Undefined";
    }
};

typedef t_AgregateDescriptionVisitor<Description<GetNumberDot> > AgregateDescriptionVisitor;

CASPP_NS_END

#include "models_templates.cc"

#endif // _CASPP_MODELS_H_
